#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mod_ftp.h"
#include "sal_module_wrapper.h"
#include "data.h"
#include "platform.h"
#include "md5.h"
#include "gtc_protocol.h"
static int  m_socket_cmd;
static int  m_socket_data;
static char m_send_buffer[1024];
static char m_recv_buffer[1024];

int32_t socket_connect(char_t *addr, int32_t port){
    char_t port_str[10]={0};
    sprintf(port_str, "%d", port);
    return tos_sal_module_connect(addr, port_str, /*TOS_SAL_PROTO_TCP*/ 0);
}

int32_t socket_send(uint8_t socket, char_t *buf, int32_t len){
    return tos_sal_module_send(socket, buf, len);
}
/*
int32_t socket_recv(uint8_t socket, char_t *buf, int32_t len, int32_t timeout){
    int32_t cnt = timeout/10;
    int32_t pos = 0;
    int32_t ret = 0;
    while(cnt--){
        ret = tos_sal_module_recv_timeout(socket, buf+pos, len-pos, 10);
        if(ret < 0){
            return ret;
        }else{
            pos += ret;
        }
        if (pos == len){
           break;
        }
    }    
    return pos;
}
*/

int32_t socket_recv(uint8_t socket, char_t *buf, int32_t len, int32_t timeout){
        return  tos_sal_module_recv_timeout(socket, buf, len, timeout);
}

int32_t socket_close(uint8_t socket){
    return tos_sal_module_close(socket);
}

//命令端口，发送命令
static int ftp_send_command(char *cmd)
{
	int ret;
	printf("send command: %s\r\n", cmd);
	ret = socket_send(m_socket_cmd, cmd, (int)strlen(cmd));
	if(ret < 0)
	{
		printf("failed to send command: %s",cmd);
		return 0;
	}
	return 1;
}
 
//命令端口，接收应答
static int ftp_recv_respond(char *resp, int len, int32_t timeout)
{
	int ret;

	len -= 1;
    ret = socket_recv(m_socket_cmd, resp, len, timeout);
    if(ret < 0)
    {
        printf("recv respond error!\r\n", ret);
        return 0;
    }
	resp[ret] = 0;
	printf("respond:%s\n", resp);
	return atoi(resp);
}
 
//设置FTP服务器为被动模式，并解析数据端口
static int ftp_enter_pasv(char *ipaddr, int *port)
{
	int ret;
	char *find;
	int a,b,c,d;
	int pa,pb;
	ret = ftp_send_command("PASV\r\n");
	if(ret != 1)
	{
		return 0;
	}
	ret = ftp_recv_respond(m_recv_buffer, 1024, 1000);
	if(ret != 227)
	{
		return 0;
	}
	find = strrchr(m_recv_buffer, '(');
	sscanf(find, "(%d,%d,%d,%d,%d,%d)", &a, &b, &c, &d, &pa, &pb);
	sprintf(ipaddr, "%d.%d.%d.%d", a, b, c, d);
	*port = pa * 256 + pb;
	return 1;
}
 
//上传文件
int  ftp_upload(char *name, void *buf, int len)
{
	int  ret;
	char ipaddr[32];
	int  port;
	
	//查询数据地址
	ret=ftp_enter_pasv(ipaddr, &port);
	if(ret != 1)
	{
		return -1;
	}
	m_socket_data=socket_connect(ipaddr, port);
	if(m_socket_data <= 0)
	{
		return -1;
	}
	//准备上传
	sprintf(m_send_buffer, "STOR %s\r\n", name);
	ret = ftp_send_command(m_send_buffer);
	if(ret != 1)
	{
		return -1;
	}
	ret = ftp_recv_respond(m_recv_buffer, 1024, 1000);
	if(ret != 150)
	{
		socket_close(m_socket_data);
		return -1;
	}
	
	//开始上传
	ret = socket_send(m_socket_data, buf, len);
	if(ret != len)
	{	
		printf("send data error!\r\n");
		socket_close(m_socket_data);
		return -1;
	}
	socket_close(m_socket_data);
 
	//上传完成，等待回应
	ret = ftp_recv_respond(m_recv_buffer, 1024, 1000);
	return (ret==226) ? 0 : -1;
}

#include "fsapi.h"

//下载文件
int  ftp_download(char *name, int len,uint8_t *md5_cal)
{
	uint8_t buf[1024]={0}; 
	int   i;
	int   ret;
	char  ipaddr[32];
	int   port;
    
	//查询数据地址
	ret = ftp_enter_pasv(ipaddr, &port);
	if(ret != 1)
	{
		return -1;
	}
	//连接数据端口
	m_socket_data = socket_connect(ipaddr, port);
	if(m_socket_data <= 0)
	{
		printf("failed to connect data port\r\n");
		return -1;
	}
 
	//准备下载
	sprintf(m_send_buffer, "RETR %s\r\n", name);
	ret = ftp_send_command(m_send_buffer);
	
	
  int32_t pos = 0;  
  int32_t read_len = 1024;
		
	//开始下载,读取完数据后，服务器会自动关闭连接
	fs_fd fd;
  if (fs_open(&fd, name, FS_O_CREAT | FS_O_RDWR) != 0) {
        return -1;
  }
  fs_lseek(&fd, 0, FS_SEEK_SET);
	printf("begin download\r\n");
	while(1)
	{				
		uint32_t ret = socket_recv(m_socket_data, buf, read_len,2000);
	
	  fs_write(&fd, buf, ret);
	  pos += ret;
		
		
		if(pos == len){
			break;
		}
    os_msleep(1);
	}
 
  fs_close(&fd);
	//下载完成
	printf("download %d/%d bytes complete.\r\n", pos, len);
	
	
	fs_fd fd_read ;
	uint32_t read_size = 0;
	uint8_t read_buffer[1024] = {0};
	if (fs_open(&fd_read, name,FS_O_RDONLY) != 0) {
        return -1;
  }
	fs_lseek(&fd_read, 0, FS_SEEK_SET);
	
	md5_state_t state;
  md5_byte_t digest[16];
  md5_init(&state);
	
	uint32_t size = fs_size(&fd_read);
	while(1){
		 if(0 == size){
			 break;
		 }
		 if(size<1024){
			 read_size = size;
		 }else{
			 read_size = 1024;
		 }
	   fs_read(&fd_read,read_buffer,read_size);
		
		 md5_append(&state, (const md5_byte_t *)read_buffer, read_size);
		 size = size - read_size;
	}
	md5_finish(&state, (md5_byte_t *)digest);
	
	
	printf("digest:");
	for(uint32_t i = 0;i<16;i++){
		printf("%02x",digest[i]);
	}
	printf("\r\n");
	
  fs_close(&fd_read);
	

	
	if(memcmp(md5_cal,digest,16) == 0){//说明MD5相等
			printf("md5 is equal\r\n");
	  	struct T_updateInfo info;
		  info.status = UPDATE_LOADED;
		  sprintf(info.name,"%s",name);
		  GtcData_SaveUpdateInfoFile((uint8_t *)&info, sizeof(info));
		  Reboot();
	}else{//说明MD5不等
		printf("md5 is not equal\r\n");
		fs_delete(name);
	}
	
	socket_close(m_socket_data);
	ret = ftp_recv_respond(m_recv_buffer, 1024, 1000);
	return (ret==226) ? 0 : -1;
}
 
//返回文件大小
int  ftp_filesize(char *name)
{
	int ret;
	int size;
	sprintf(m_send_buffer,"SIZE %s\r\n",name);
	ret = ftp_send_command(m_send_buffer);
	if(ret != 1)
	{
		return -1;
	}
	ret = ftp_recv_respond(m_recv_buffer, 1024, 1000);
	if(ret != 213)
	{
		return -1;
	}
	size = atoi(m_recv_buffer + 4);
	return size;
}
 
//登陆服务器
int ftp_login(char *addr, int port, char *username, char *password)
{
	int ret;
	printf("connect...\r\n");
	m_socket_cmd = socket_connect(addr, port);
	if(m_socket_cmd <= 0)
	{
		printf("connect server failed!\r\n");
		return -1;
	}
	printf("connect ok.\r\n");
    //等待欢迎信息
	ret = ftp_recv_respond(m_recv_buffer, 1024, 2000);
	if(ret != 220)
	{
		printf("bad server, ret=%d!\r\n", ret);
		socket_close(m_socket_cmd);
		return -1;
	}
	
	printf("login...\r\n");
    //发送USER
	sprintf(m_send_buffer, "USER %s\r\n", username);
	ret = ftp_send_command(m_send_buffer);
	if(ret != 1)
	{
        printf("333333333333333333333333333\n");
		socket_close(m_socket_cmd);
		return -1;
	}

	ret = ftp_recv_respond(m_recv_buffer, 1024, 1000);
	if(ret != 331)
	{
        printf("4444444444444444444444444444\n");
		socket_close(m_socket_cmd);
		return -1;
	}
	
    //发送PASS
	sprintf(m_send_buffer, "PASS %s\r\n", password);
	ret = ftp_send_command(m_send_buffer);
	if(ret != 1)
	{
        printf("555555555555555555555555555555\n");
		socket_close(m_socket_cmd);
		return -1;
	}
	ret = ftp_recv_respond(m_recv_buffer, 1024, 20000);
	if(ret != 230)
	{
      printf("666666666666666666666666666666666\n");
		socket_close(m_socket_cmd);
		return -1;
	}
	printf("login success.\r\n");
	
    //设置为二进制模式
	ret = ftp_send_command("TYPE I\r\n");
	if(ret != 1)
	{
    printf("777777777777777777777777777777777\n");
		socket_close(m_socket_cmd);
		return -1;
	}
	ret = ftp_recv_respond(m_recv_buffer, 1024,10000);
	if(ret != 200)
	{
        printf("888888888888888888888888888888\n");
		socket_close(m_socket_cmd);
		return -1;
	}
	return 0;
}
 
void ftp_quit(void)
{
	ftp_send_command("QUIT\r\n");
	socket_close(m_socket_cmd);
}

